﻿#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
#endregion

namespace DirectZZT.Shared.Input
{
    /// <summary>
    /// Defines mechanisms for an input manager handling the inputs.
    /// </summary>
    public interface IInputManager : IDisposable
    {
        /// <summary>
        /// Returns the devices that this input manager handles.
        /// </summary>
        InputManagerDevices HandledDevices { get; }
        /// <summary>
        /// Gets/sets the cursor position.
        /// </summary>
        Vector2 CursorPosition { get; set; }

        /// <summary>
        /// Returns all existing bindings that have been set.
        /// </summary>
        /// <returns>All existing bindings that have been set.</returns>
        IEnumerable<InputBinding> GetBindings();
        /// <summary>
        /// Binds the given action to the given code.
        /// </summary>
        /// <param name="action">The action to bind.</param>
        /// <param name="code">The code to bind to. This is specific to the implementing <see cref="IInputManager"/>.</param>
        void Bind(string action, int code);
        /// <summary>
        /// Removes all bindings of the given action.
        /// </summary>
        /// <param name="action">The action to remove the binding from.</param>
        void UnBind(string action);
        /// <summary>
        /// Registers a new <see cref="InputCommand"/> to this instance.
        /// </summary>
        /// <param name="name">The name of the command. This is the same name as the "action" later.</param>
        /// <param name="command">The command to register.</param>
        void RegisterCommand(string name, InputCommand command);

        /// <summary>
        /// Returns whether or not the given action is currently invoked.
        /// See documentation for further information.
        /// </summary>
        /// <remarks>This method returns <c>true</c> whenever the action is invoked at the time of this method's call.
        /// This method doesn't consider the state of the action between the current and previous call.
        /// For that, use <see cref="GetActionInvokedToggle(string)"/>.</remarks>
        /// <param name="action">The action to check for being invoked currently.</param>
        /// <returns>A boolean value indicating whether or not the given action is currently invoked.</returns>
        bool GetActionInvoked(string action);
        /// <summary>
        /// Returns whether or not the given action is invoked in the current frame, but wasn't in the previous frame.
        /// </summary>
        /// <param name="action">The action to check.</param>
        /// <returns>A boolean value indicating whether or not the given action is invoked in the current frame, but wasn't in the previous frame.</returns>
        bool GetActionInvokedToggle(string action);
        /// <summary>
        /// Returns the value of the given action, if it is a valued action.
        /// Valued actions might include mouse, joystick or gamepad axis'.
        /// </summary>
        /// <param name="action">The action to check.</param>
        /// <returns>A float containing the value of the valued action. This returns <see cref="System.Single.MinValue"/> if the action had no value (wasn't invoked).</returns>
        float GetActionValue(string action);
        /// <summary>
        /// Returns whether or not any key is invoked.
        /// </summary>
        /// <returns>Whether or not any key is invoked.</returns>
        bool IsAnyKey();

        /// <summary>
        /// Called once per frame and updates the action states.
        /// </summary>
        void Update();
    }
}
